package org.gavin.core.conf;

import cn.hutool.core.date.DateUtil;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import org.gavin.core.constant.CommonConst;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.support.WebBindingInitializer;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;

import java.beans.PropertyEditorSupport;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * 全局转换配置
 *
 * @author grl
 * @date 2024/1/5
 */
@Configuration
public class ConverterConfig {
    /**
     * string转localDate
     * 与下方 RequestMappingHandlerAdapter 功能一致
     * 启用 则加上 @Bean
     */
    public Converter<String, LocalDate> localDateConverter() {
        return new Converter<String, LocalDate>() {
            @Override
            public LocalDate convert(String source) {
                if (source.trim().length() == 0) {
                    return null;
                }
                try {
                    return LocalDate.parse(source, DateTimeFormatter.ofPattern(CommonConst.DATE_PATTERN));
                } catch (Exception e) {
                    return LocalDate.parse(source);
                }
            }
        };
    }

    /**
     * string转localdatetime
     * 与下方 RequestMappingHandlerAdapter 功能一致
     * 启用 则加上 @Bean
     */
    public Converter<String, LocalDateTime> localDateTimeConverter() {
        return new Converter<String, LocalDateTime>() {
            @Override
            public LocalDateTime convert(String source) {
                if (source.trim().length() == 0) {
                    return null;
                }
                // 先尝试ISO格式: 2019-07-15T16:00:00
                try {
                    return LocalDateTime.parse(source, DateTimeFormatter.ofPattern(CommonConst.DATE_TIME_PATTERN));
                } catch (Exception e) {
                    return LocalDateTime.parse(source);
                }
            }
        };
    }

    /**
     * 兼容 formData GET Query传参 时间转换
     *
     * @param requestMappingHandlerAdapter
     * @return
     */
    @Bean
    public RequestMappingHandlerAdapter webBindingInitializer(RequestMappingHandlerAdapter requestMappingHandlerAdapter) {
        requestMappingHandlerAdapter.setWebBindingInitializer(new WebBindingInitializer() {
            @Override
            public void initBinder(WebDataBinder binder) {
                binder.registerCustomEditor(LocalDateTime.class, new PropertyEditorSupport() {
                    @Override
                    public void setAsText(String text) {
                        setValue(DateUtil.parseLocalDateTime(text));
                    }
                });
                binder.registerCustomEditor(LocalDate.class, new PropertyEditorSupport() {
                    @Override
                    public void setAsText(String text) {
                        setValue(LocalDate.parse(text, DateTimeFormatter.ofPattern(CommonConst.DATE_PATTERN)));
                    }
                });
                binder.registerCustomEditor(String.class,
                        new StringTrimmerEditor(true));
            }
        });
        return requestMappingHandlerAdapter;
    }

    /**
     * 仅对JSON传参请求 响应 对象数据格式转换
     * 统一配置
     */
    @Bean
    public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() {
        JavaTimeModule module = new JavaTimeModule();
        LocalDateTimeDeserializer localDateTimeDeserializer = new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(CommonConst.DATE_TIME_PATTERN));
        module.addDeserializer(LocalDateTime.class, localDateTimeDeserializer);
        return builder -> {
            builder.simpleDateFormat(CommonConst.DATE_TIME_PATTERN);
            builder.serializers(new LocalDateSerializer(DateTimeFormatter.ofPattern(CommonConst.DATE_PATTERN)));
            builder.serializers(new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(CommonConst.DATE_TIME_PATTERN)));
            builder.modules(module);
        };
    }
}
